package com.hnblc.blcwms.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hnblc.blcwms.common.constant.StringPool;
import com.hnblc.blcwms.common.interaction.Response;
import com.hnblc.blcwms.persistent.business.odata.entity.OdataExpM;
import com.hnblc.blcwms.persistent.business.odata.service.IOdataExpMService;
import com.hnblc.blcwms.persistent.business.odata.vo.ExpressInfoHead;
import com.hnblc.blcwms.persistent.business.odata.vo.ExpressQueryVO;
import com.hnblc.blcwms.rest.logistics.enums.LogisticCompanyEnum;
import com.hnblc.blcwms.rest.logistics.enums.STOResultEnum;
import com.hnblc.blcwms.rest.logistics.enums.WaybillResultEnum;
import com.hnblc.blcwms.rest.logistics.service.PDDService;
import com.hnblc.blcwms.rest.logistics.service.STOService;
import com.hnblc.blcwms.rest.logistics.service.YTOService;
import com.hnblc.blcwms.rest.logistics.vo.PDDPrintData;
import com.hnblc.blcwms.serviceapi.api.dto.logistics.WaybillInfo;
import com.hnblc.blcwms.serviceapi.api.service.ILogisticsApplyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class LogisticsApplyService implements ILogisticsApplyService {


    Logger logger = LoggerFactory.getLogger(LogisticsApplyService.class);

    @Autowired
    ObjectMapper objectMapper;
    @Autowired
    PDDService pddService;
    @Autowired
    YTOService ytoService;
    @Autowired
    STOService stoService;
    @Autowired
    IOdataExpMService odataExpMService;

    @Override
    public Response<List<WaybillInfo>> applyWaybillInfo(ExpressQueryVO expressQueryVO,String logisticNo) {


        //加载获取运单号所用内容
        List<ExpressInfoHead> expressInfoHeads = odataExpMService.getExpressFullInfo(expressQueryVO);

        if (expressInfoHeads.size()<1){
            return new Response<>(WaybillResultEnum.ERROR_EXP_NOT_FOUND);
        }
        if (LogisticCompanyEnum.PDD_YTO.getTextEn().equalsIgnoreCase(logisticNo)){
            return this.applyPDDYTOWaybillInfo(expressInfoHeads);
        }else if (LogisticCompanyEnum.YTO.getTextEn().equalsIgnoreCase(logisticNo)){
            //TODO 批量获取圆通快递地址
            return new Response<>(WaybillResultEnum.ERROR_LOGISTIC_CODE, new Object[]{logisticNo});
        }else if (LogisticCompanyEnum.STO.getTextEn().equalsIgnoreCase(logisticNo)){
            return this.applySTOWaybillInfo(expressInfoHeads);
        }else if (LogisticCompanyEnum.SF.getTextEn().equalsIgnoreCase(logisticNo)){
            //TODO 批量获取顺丰快递地址
            return new Response<>(WaybillResultEnum.ERROR_LOGISTIC_CODE, new Object[]{logisticNo});
        }else {
            return new Response<>(WaybillResultEnum.ERROR_WRONG_LOGISTIC_CODE, new Object[]{logisticNo});
        }
    }

    @Override
    public Response<List<WaybillInfo>> applyPDDYTOWaybillInfo(List<ExpressInfoHead> expressInfoHeads) {

        /**
         * 判断订单是否为拼多多订单
         */
        //TODO 来源平台代码暂时写再代码里，后期处理
        if("PF000003".equalsIgnoreCase(expressInfoHeads.get(0).getOrderSource())){
            return new Response<>(WaybillResultEnum.PDD_ERROR_EXP_WRONG_SOURCE,new Object[]{expressInfoHeads.get(0).getExpNo(),
            expressInfoHeads.get(0).getOrderSource()});
        }

        /**
         * 请求运单号并写入运单号
         */
        //TODO 查询物流商为中文，后期优化

        Response<List<WaybillInfo>> waybillInfoResponse = pddService.getWaybillInfo(expressInfoHeads,false,"圆通");
        if (!waybillInfoResponse.isSuccess()){
            return  waybillInfoResponse;
        }
        List<WaybillInfo> waybillInfos = waybillInfoResponse.getResponseData();

        for (WaybillInfo waybillInfo : waybillInfos) {
            PDDPrintData waybillDetail;
            try {
                waybillDetail = objectMapper.readValue(waybillInfo.getPrintData(), new TypeReference<PDDPrintData>(){});
                if (waybillDetail!=null&&waybillDetail.getRoutingInfo()!=null){
                    waybillInfo.setDeliveryAddress(waybillDetail.getRoutingInfo().getThreeSegmentCode());
                    waybillInfo.setEndBranchName(waybillDetail.getRoutingInfo().getEndBranchName());
                    waybillInfo.setEndBranchCode(waybillDetail.getRoutingInfo().getEndBranchCode());
                    waybillInfo.setBigShotCode(waybillDetail.getRoutingInfo().getBigShotCode());
                    waybillInfo.setBigShotName(waybillDetail.getRoutingInfo().getBigShotName());
                }

            } catch (Exception e) {
                e.printStackTrace();
                logger.error("error occurred when get threeSegCode from printData "+waybillInfo.getPrintData()+",detail: "+e.getMessage());
            }
        }
        if (waybillInfos!=null && waybillInfos.size()>0){
            for (WaybillInfo waybillInfo : waybillInfos) {
                String[] id = waybillInfo.getObjectId().split(StringPool.COMMON_SEPARATOR_SPLIT_COLON);
                odataExpMService.update(new UpdateWrapper<OdataExpM>().set("shipper_deliver_no",waybillInfo.getWaybillNo())
                        //TODO 更新出货单承运商字段
                        .set("deliver_address",waybillInfo.getDeliveryAddress())   //三段码
                        .set("RSV_VAROD5",waybillInfo.getEndBranchCode())          //目的集运点代码
                        .set("RSV_VAROD6",waybillInfo.getEndBranchName())          //目的集运点名称
                        .set("RSV_VAROD7",waybillInfo.getBigShotCode())            //大头笔条码
                        .set("RSV_VAROD8",waybillInfo.getBigShotName())            //大头笔名称
                        .eq("enterprise_no",id[0])
                        .eq("warehouse_no",id[1])
                        .eq("exp_no",id[2]));
            }
        }

        return waybillInfoResponse;
    }

    @Override
    public Response<List<WaybillInfo>> applyYTOWaybillInfo(List<ExpressInfoHead> expressInfoHeads) {



        /**
         * 请求运单号并写入运单号
         */
        Response<List<WaybillInfo>> waybillInfoResponse = ytoService.getWaybillInfo(expressInfoHeads);
        if (!waybillInfoResponse.isSuccess()){
            return  waybillInfoResponse;
        }
        /*//批量更新数据库
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(
                jdbcTemplate.getDataSource());
        TransactionStatus status = transactionManager.getTransaction(def);

        try {
//			jdbcTemplate.getDataSource()
//			.getConnection()
//			.setAutoCommit(false);
            final List<Map<String,String>> paramList = responseList;
            String sql = "update odata_exp_m@zdmwms oem set oem.shipper_deliver_no = ?,oem.DELIVER_ADDRESS = ? where oem.exp_no = ?";
            jdbcTemplate.batchUpdate(sql,
                    new BatchPreparedStatementSetter() {
                        public void setValues(
                                PreparedStatement ps, int i)
                                throws SQLException {

                            ps.setString(1, paramList.get(i).get("waybillNo"));
                            ps.setString(2, paramList.get(i).get("deleveryAddress"));
                            ps.setString(3, paramList.get(i).get("expNo"));

                        }

                        public int getBatchSize() {
                            return paramList.size();
                        }
                    });

        } catch (Exception e) {
            System.out
                    .println("----------RuntimeException-----when update logisticMessage"
                            + e);
            status.setRollbackOnly(); // 回滚
            e.printStackTrace();
            errorDetail.append("更新数据库失败。");
        } finally {
            try {
                transactionManager.commit(status);
//				jdbcTemplate.getDataSource().getConnection()
//						.setAutoCommit(true);
//				jdbcTemplate.getDataSource().getConnection()
//						.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if(errorDetail.length()>0){
            responseData.setMsgCode(ResponseData.CODE_ERROR);
            responseData.setMsgData(errorExpNo.toString());
            responseData.setMsgDetail(errorDetail.toString());
        }
        return responseData;*/

        return null;
    }

    @Override
    public Response<List<WaybillInfo>> applySTOWaybillInfo(List<ExpressInfoHead> expressInfoHeads) {

        //获取运单号段
        List<String> waybillNos;
        Response<List<String>> nosRes = stoService.getWaybillNos(expressInfoHeads.size());
        if (!nosRes.isSuccess()){
            return new Response<>(STOResultEnum.ERROR_UNKNOWN,new Object[]{nosRes});
        }
        waybillNos = nosRes.getResponseData();
        if (waybillNos.size()<1) {
            return new Response<>(STOResultEnum.EMPTY_NO_DATA);
        }
        //匹配并使用运单号
        List<ExpressInfoHead> filledExp = new ArrayList();
        for (int i = 0; i < expressInfoHeads.size(); i++) {
            ExpressInfoHead expressHead =  expressInfoHeads.get(i);
            try{
                expressHead.setWaybillNo(waybillNos.get(i));
                filledExp.add(expressHead);
            }catch (IndexOutOfBoundsException e){
                logger.error("single requested waybill numbers not enough for expresses");
                break;
            }catch (Exception e){
                logger.error("error occurred when fill STO waybill Number to express:"+e);
                break;
            }
        }
        //批量上传订单信息，并获取运单分拨信息
        List<WaybillInfo> waybillInfos;
        Response<List<WaybillInfo>> singleResult = stoService.getWaybillInfos(filledExp); //此处使用成功匹配运单号的数据
        if (singleResult.isSuccess()){
            waybillInfos = singleResult.getResponseData();
        }else{
            return new Response<>(STOResultEnum.ERROR_RES_UPLOAD_INFO,new Object[]{
                    singleResult
            });
        }


        //更新数据库
        if (waybillInfos!=null && waybillInfos.size()>0){
            for (WaybillInfo waybillInfo : waybillInfos) {
                String[] id = waybillInfo.getObjectId().split(StringPool.COMMON_SEPARATOR_SPLIT_COLON);
                odataExpMService.update(new UpdateWrapper<OdataExpM>().set("shipper_deliver_no",waybillInfo.getWaybillNo())
                        //TODO 更新出货单承运商字段
                        .set("shipper_no","L0003")
                        .set("deliver_address",waybillInfo.getDeliveryAddress())   //三段码
                        .set("RSV_VAROD5",waybillInfo.getEndBranchCode())          //目的集运点代码
                        .set("RSV_VAROD6",waybillInfo.getEndBranchName())          //目的集运点名称
                        .set("RSV_VAROD7",waybillInfo.getBigShotCode())            //大头笔条码
                        .set("RSV_VAROD8",waybillInfo.getBigShotName())            //大头笔名称
                        .eq("enterprise_no",id[0])
                        .eq("warehouse_no",id[1])
                        .eq("exp_no",id[2]));
            }
        }

        //部分成功，单次申请运单号不足
        if (filledExp.size()<expressInfoHeads.size()){
            return new Response<>(STOResultEnum.NO_NOT_ENOUGH,waybillInfos);
        }
        //部分成功，上传信息部分失败
        if (waybillInfos.size()<filledExp.size()){
            return new Response<>(STOResultEnum.NOT_ALL_SUC,waybillInfos,new Object[]{
                    singleResult.getFailedMessage()
            });
        }
        //全部成功
        return new Response<>(STOResultEnum.SUCCESS,waybillInfos);
    }

    @Override
    public Response<WaybillInfo> getYTOThreeSegCode(List<ExpressInfoHead> expressInfoHeads) {
        return null;
    }

    @Override
    public Response<WaybillInfo> getSFThreeSegCode(List<ExpressInfoHead> expressInfoHeads) {
        return null;
    }

    @Override
    public Response<WaybillInfo> getSTThreeSegCode(List<ExpressInfoHead> expressInfoHeads) {
        return null;
    }

    @Override
    public Response<WaybillInfo> getYDThreeSegCode(List<ExpressInfoHead> expressInfoHeads) {
        return null;
    }
}
